home *** CD-ROM | disk | FTP | other *** search
/ Download Now 8 / Download Now V8.iso / Program / InternetTools / ApacheWebServer1.3.6 / apache_1_3_6_win32.exe / _SETUP.1 / service.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-10  |  7.9 KB  |  317 lines

  1. #ifdef WIN32
  2.  
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <process.h>
  7. #include <direct.h>
  8.  
  9. #include "httpd.h"
  10. #include "http_conf_globals.h"
  11. #include "http_log.h"
  12. #include "http_main.h"
  13. #include "multithread.h"
  14. #include "service.h"
  15. #include "registry.h"
  16.  
  17. static struct
  18. {
  19.     int (*main_fn)(int, char **);
  20.     event *stop_event;
  21.     int connected;
  22.     SERVICE_STATUS_HANDLE hServiceStatus;
  23.     char *name;
  24.     int exit_status;
  25.     SERVICE_STATUS ssStatus;
  26.     FILE *logFile;
  27. } globdat;
  28.  
  29. static void WINAPI service_main_fn(DWORD, char **);
  30. static void WINAPI service_ctrl(DWORD ctrlCode);
  31. static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint);
  32. static void InstallService();
  33. static void RemoveService();
  34.  
  35.  
  36. int service_main(int (*main_fn)(int, char **), int argc, char **argv,
  37.                   char *service_name,
  38.                   int install_flag, int run_as_service)
  39. {
  40.     SERVICE_TABLE_ENTRY dispatchTable[] =
  41.     {
  42.         { service_name, service_main_fn },
  43.         { NULL, NULL }
  44.     };
  45.  
  46.     globdat.name = service_name;
  47.  
  48.     if(install_flag > 0)
  49.     {
  50.         InstallService();
  51.         return(0);
  52.     }
  53.     else if(install_flag < 0)
  54.     {
  55.         RemoveService();
  56.         return(0);
  57.     }
  58.     else
  59.     {
  60.         globdat.main_fn = main_fn;
  61.         globdat.stop_event = create_event(0, 0, "apache-signal");
  62.      
  63.         if(run_as_service)
  64.         {
  65.             globdat.connected = 1;
  66.             if(!StartServiceCtrlDispatcher(dispatchTable))
  67.             {
  68.                 return((*main_fn)(argc, argv));
  69.             }
  70.             else
  71.             {
  72.                 return(globdat.exit_status);
  73.             }
  74.         }
  75.         else
  76.         {
  77.             globdat.connected = 0;
  78.             return((*main_fn)(argc, argv));
  79.         }
  80.     }
  81.  
  82. }
  83.  
  84. void service_cd()
  85. {
  86.     /* change to the drive with the executable */
  87.     char buf[300];
  88.     GetModuleFileName(NULL, buf, 300);
  89.     buf[2] = 0;
  90.     chdir(buf);
  91. }
  92.  
  93. void __stdcall service_main_fn(DWORD argc, char **argv)
  94. {
  95.  
  96.  
  97.     if(!(globdat.hServiceStatus = RegisterServiceCtrlHandler( globdat.name, service_ctrl)))
  98.     {
  99.         globdat.exit_status = -1;
  100.         return;
  101.     }
  102.  
  103.  
  104.     ReportStatusToSCMgr(
  105.         SERVICE_START_PENDING, // service state
  106.         NO_ERROR,              // exit code
  107.         3000);                 // wait hint
  108.  
  109.     globdat.exit_status = (*globdat.main_fn)( argc, argv );
  110.  
  111.  
  112.     ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0);
  113.  
  114.     return;
  115. }
  116.  
  117. void service_set_status(int status)
  118. {
  119.     ReportStatusToSCMgr(status, NO_ERROR, 3000);
  120. }
  121.  
  122.  
  123.  
  124. //
  125. //  FUNCTION: service_ctrl
  126. //
  127. //  PURPOSE: This function is called by the SCM whenever
  128. //           ControlService() is called on this service.
  129. //
  130. //  PARAMETERS:
  131. //    dwCtrlCode - type of control requested
  132. //
  133. //  RETURN VALUE:
  134. //    none
  135. //
  136. //  COMMENTS:
  137. //
  138. VOID WINAPI service_ctrl(DWORD dwCtrlCode)
  139. {
  140.     int state;
  141.  
  142.  
  143.     state = globdat.ssStatus.dwCurrentState;
  144.     switch(dwCtrlCode)
  145.     {
  146.         // Stop the service.
  147.         //
  148.         case SERVICE_CONTROL_STOP:
  149.             state = SERVICE_STOP_PENDING;
  150.         ap_start_shutdown();
  151.             break;
  152.  
  153.         // Update the service status.
  154.         //
  155.         case SERVICE_CONTROL_INTERROGATE:
  156.             break;
  157.  
  158.         // invalid control code
  159.         //
  160.         default:
  161.             break;
  162.  
  163.     }
  164.  
  165.     ReportStatusToSCMgr(state, NO_ERROR, 0);
  166. }
  167.  
  168.  
  169. int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint)
  170. {
  171.     static int firstTime = 1;
  172.     static int checkPoint = 1;
  173.     int rv;
  174.     
  175.     if(firstTime)
  176.     {
  177.         firstTime = 0;
  178.         globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  179.         globdat.ssStatus.dwServiceSpecificExitCode = 0;
  180.         globdat.ssStatus.dwCheckPoint = 1;
  181.     }
  182.  
  183.     if(globdat.connected)
  184.     {
  185.         if (currentState == SERVICE_START_PENDING)
  186.             globdat.ssStatus.dwControlsAccepted = 0;
  187.         else
  188.             globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  189.  
  190.         globdat.ssStatus.dwCurrentState = currentState;
  191.         globdat.ssStatus.dwWin32ExitCode = exitCode;
  192.         if(waitHint)
  193.             globdat.ssStatus.dwWaitHint = waitHint;
  194.  
  195.         if ( ( currentState == SERVICE_RUNNING ) ||
  196.              ( currentState == SERVICE_STOPPED ) )
  197.         {
  198.             globdat.ssStatus.dwWaitHint = 0;
  199.             globdat.ssStatus.dwCheckPoint = 0;
  200.         }
  201.         else
  202.             globdat.ssStatus.dwCheckPoint = ++checkPoint;
  203.  
  204.         rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus);
  205.  
  206.     }
  207.     return(1);
  208. }
  209.  
  210.  
  211. void InstallService()
  212. {
  213.     SC_HANDLE   schService;
  214.     SC_HANDLE   schSCManager;
  215.  
  216.     TCHAR szPath[512];
  217.  
  218.     if (GetModuleFileName( NULL, szPath, 512 ) == 0)
  219.     {
  220.         exit(1);
  221.         return;
  222.     }
  223.  
  224.     schSCManager = OpenSCManager(
  225.                         NULL,                   // machine (NULL == local)
  226.                         NULL,                   // database (NULL == default)
  227.                         SC_MANAGER_ALL_ACCESS   // access required
  228.                         );
  229.    if (!schSCManager) {
  230.        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  231.        "OpenSCManager failed");
  232.     }
  233.     else {
  234.         schService = CreateService(
  235.             schSCManager,               // SCManager database
  236.             globdat.name,        // name of service
  237.             globdat.name, // name to display
  238.             SERVICE_ALL_ACCESS,         // desired access
  239.             SERVICE_WIN32_OWN_PROCESS,  // service type
  240.             SERVICE_AUTO_START,       // start type
  241.             SERVICE_ERROR_NORMAL,       // error control type
  242.             szPath,                     // service's binary
  243.             NULL,                       // no load ordering group
  244.             NULL,                       // no tag identifier
  245.             NULL,       // dependencies
  246.             NULL,                       // LocalSystem account
  247.             NULL);                      // no password
  248.  
  249.         if (schService) {
  250.             CloseServiceHandle(schService);
  251.  
  252.         /* Now store the server_root in the registry */
  253.         ap_registry_set_server_root(ap_server_root);
  254.         }
  255.         else {
  256.             ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, 
  257.         "CreateService failed");
  258.         }
  259.  
  260.         CloseServiceHandle(schSCManager);
  261.     }
  262.  
  263. }
  264.  
  265.  
  266.  
  267.  
  268. void RemoveService()
  269. {
  270.     SC_HANDLE   schService;
  271.     SC_HANDLE   schSCManager;
  272.  
  273.     schSCManager = OpenSCManager(
  274.                         NULL,                   // machine (NULL == local)
  275.                         NULL,                   // database (NULL == default)
  276.                         SC_MANAGER_ALL_ACCESS   // access required
  277.                         );
  278.     if (!schSCManager) {
  279.        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  280.        "OpenSCManager failed");
  281.     }
  282.     else {
  283.         schService = OpenService(schSCManager, globdat.name, SERVICE_ALL_ACCESS);
  284.  
  285.         if (schService == NULL) {
  286.             /* Could not open the service */
  287.            ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  288.             "OpenService failed");
  289.         }
  290.         else {
  291.             /* try to stop the service */
  292.             if (ControlService(schService, SERVICE_CONTROL_STOP, &globdat.ssStatus)) {
  293.                 Sleep(1000);
  294.                 while(QueryServiceStatus(schService, &globdat.ssStatus)) {
  295.                     if(globdat.ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
  296.                         Sleep(1000);
  297.                     else
  298.                         break;
  299.                 }
  300.             }
  301.  
  302.             // now remove the service
  303.             if (DeleteService(schService) == 0)
  304.         ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
  305.             "DeleteService failed");
  306.             CloseServiceHandle(schService);
  307.         }
  308.  
  309.         CloseServiceHandle(schSCManager);
  310.     }
  311.  
  312. }
  313.  
  314. #endif /* WIN32 */
  315.  
  316.  
  317.